package drds.configuration.db.xml_mapping.sql_execute;

import drds.configuration.db.xml_mapping.MapperFactory;
import drds.configuration.db.xml_mapping.annotation.dto.Dto;
import drds.configuration.db.xml_mapping.annotation.dto.DtoMapping;
import drds.configuration.db.xml_mapping.annotation.mapper_class.Key;
import drds.configuration.db.xml_mapping.configuration.ParameterMap;
import drds.configuration.db.xml_mapping.configuration.ParameterMapping;
import drds.tools.$;
import lombok.NonNull;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MethodArgsToNamedMap {
    //

    /**
     * 入参处理为map
     */
    public static Map<String, Object> convertArgsToNamedParameterMap(Method method, Object[] args, Mapper mapper) {
        int parameterCount = method.getParameterCount();
        //Class[] parameterTypes = method.getParameterTypes();
        //注解匹配
        Annotation[][] annotationss = method.getParameterAnnotations();
        if (parameterCount != annotationss.length) {
            throw new IllegalArgumentException("入参个数大于入参注解的个数");
        }
        if (args.length != parameterCount) {
            throw new IllegalArgumentException("入参个数大于实际入参的个数");
        }
        Map<String, Object> aliasMap = new HashMap<String, Object>();
        for (int i = 0; i < annotationss.length; i++) {
            Annotation[] annotations = annotationss[i];
            boolean has = false;
            for (Annotation annotation : annotations) {
                if (has) {
                    throw new IllegalArgumentException("请不要重复设置Key注解");
                }
                if (annotation instanceof Key) {
                    has = true;
                    Key key = (Key) annotation;
                    String value = key.key();
                    if (value == null) {
                        throw new IllegalArgumentException();
                    }
                    if (aliasMap.containsKey(value)) {
                        throw new IllegalArgumentException("请不要重复为入参设置相同的Key");
                    }
                    if ($.isNullOrEmpty(value)) {
                        throw new IllegalArgumentException();
                    } else {
                        try {
                            //如果是基本类型,别名就是key,需要针对非基本类型,map,List<DTO>需要转为List<Map>
                            aliasMap.put(value, toMap(mapper, args[i]));
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                            throw new IllegalArgumentException(e);
                        }
                    }

                }
            }
        }

        return aliasMap;
    }

    public static Object toMap(Mapper mapper, Object object) throws IllegalAccessException {
        if (object instanceof ArrayList) {
            if (((ArrayList) object).get(0) instanceof Map) {
                return object;
            } else {
                if (((ArrayList) object).get(0).getClass().getAnnotation(Dto.class) != null) {
                    //每个进行遍历
                    List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
                    ArrayList list = (ArrayList) object;
                    for (Object value : list) {
                        mapList.add(toMapFromDto(mapper, value));
                    }
                    return mapList;
                } else {
                    //非map直接保存
                    return object;
                }
            }
        } else {
            if (object instanceof HashMap) {
                return object;
            } else {
                if (object.getClass().getAnnotation(Dto.class) != null) {
                    //每个进行遍历
                    return toMapFromDto(mapper, object);
                } else {
                    //非map直接保存
                    return object;
                }
            }
        }
    }

    /**
     * 如果配置了ParameterMap,则优先使用这个,否则使用dto自己的映射关系
     */
    public static Map<String, Object> toMapFromDto(Mapper mapper, @NonNull Object object) throws IllegalAccessException {
        if (object.getClass().getAnnotation(Dto.class) == null) {
            throw new IllegalArgumentException();
        } else {
            if (mapper.getParameterMap() == null) {
                Map<String, Object> map = new HashMap<String, Object>();
                DtoMapping dtoMapping = MapperFactory.DtoClassMapping.classToDtoMappingMap.get(object.getClass());
                Map<String, Field> columnNameToFieldMap = dtoMapping.getColumnNameToFieldMap();
                for (Map.Entry<String, Field> entry : columnNameToFieldMap.entrySet()) {
                    Field field = entry.getValue();
                    map.put(entry.getKey(), field.get(object));
                }
                return map;
            } else {
                ParameterMap parameterMap = mapper.getParameterMap();
                Class clazz = parameterMap.getParameterClass();
                if (clazz == null) {
                    throw new IllegalArgumentException(mapper.getId() + "parameterClass为空");
                }
                List<ParameterMapping> parameterMappingList = parameterMap.getParameterMappingList();
                Map<String, Object> map = new HashMap<String, Object>();
                for (ParameterMapping parameterMapping : parameterMappingList) {
                    Field field = null;
                    try {
                        field = clazz.getDeclaredField(parameterMapping.getPropertyName());
                        field.setAccessible(true);
                    } catch (NoSuchFieldException e) {
                        throw new IllegalArgumentException(mapper.getId() + "parameterClass:" + clazz + "缺少字段" + parameterMapping.getPropertyName());
                    }
                    map.put(parameterMapping.getColumnName(), field.get(object));
                }
                return map;
            }

        }
    }
}
